doubleとinstance double
RSpecでテストを書く際のモック(Test Double)には、主にdoubleとinstance_doubleという2つの重要な機能がある。 使い分け
table:table
機能 自由度 安全性 使用場面
double 高 低 プロトタイプ、外部API
instance_double 中 高 基本的にはこっち、既存クラス
一般的に、本格的なアプリケーション開発ではinstance_doubleを使用する
型安全性とメンテナンス性が向上するため
double
code: (ruby)
let(:user_double) { double("User") }
特徴
完全に自由なスタブオブジェクト
実際のクラスの構造とは無関係に任意のメソッドを定義可能
柔軟で素早くテストが書ける
タイポや実際のクラスとの不整合を検出できない
使用場面
外部APIレスポンスなど、厳密なクラス構造が不要な場合
プロトタイプ段階で迅速にテストを作成したい場合
instance_double
code: (ruby)
let(:user_double) { instance_double(User) }
特徴
指定したクラスの実際のインスタンスメソッドのみ模倣可能
実在するメソッドしかスタブできない
タイプセーフティとリファクタリング安全性
実際のクラスが必要で、やや制約が強い
使用場面
アプリケーション内の既存クラスをモックする場合
リファクタリング時の安全性を重視する場合
チーム開発でのタイポ防止を重視する場合
実用的なコード例
code: (ruby)
# doubleの例(自由度が高い)
user_double = double("User")
allow(user_double).to receive(:nonexistent_method).and_return("OK") # エラーにならない
# instance_doubleの例(安全性が高い)
user_double = instance_double(User)
allow(user_double).to receive(:name).and_return("John") # Userクラスにnameメソッドがある場合のみ成功
# allow(user_double).to receive(:nonexistent_method) # エラーになる